<?php

class FP_Application_Subsystem_Acl implements FP_Application_Subsystem_Interface {

    public static $enabled = true;

    protected $_config = null;

    public function init($pConfig=null){

	$this->_config = $pConfig;
	self::$enabled = $this->_config->enabled;

	if (self::$enabled && !FP_Application::Get('DISABLE_ACL')){
	    $acl = new Zend_Acl();

	    /* Reflect all of the controllers and assign all actions as acl resources */

	    $controller_names = FP_Application::getControllerNames();

	    foreach ($controller_names as $controller){

		$c = new Zend_Reflection_Class($controller);

		$methods = $c->getMethods();

		foreach ($methods as $method){

		    if (preg_match('/^(.*)Action$/i', $method->getName(), $matches)){

			$action_name = $matches[1];
			$controller_name = strtolower(preg_replace('/Controller$/', '', $controller));

			$acl->add(new Zend_Acl_Resource("{$controller_name}.{$action_name}"));

		    }

		}

	    }

	    /* Create roles from the database and assign their permissions */

 	    $Roles = FP_Application::classFactory('Roles');

	    $roles = $Roles->fetch();

	    $resources = $acl->getResources();

	    foreach ($roles as $role){

		$proles = $role->getParentRoles();

		$parents = array();

		foreach ($proles as $prole){
		    $parents[] = $prole->getRoleId();
		}

		if (!$acl->hasRole($role)){
// 		    logdebug('FP_Application_Subsystem_Acl.init: Adding role ' . $role->getRoleId() . ' with parents ' . logobject($parents));
		    $acl->addRole($role, $parents);

		    $role_permissions = $role->getPermissions();

		    foreach ($role_permissions as $rpermission){
			if ($rpermission->resource && $rpermission->privilege){
			    if (!in_array($rpermission->resource, $resources)){
				$acl->addResource(new Zend_Acl_Resource($rpermission->resource));
				$resources[] = $rpermission->resource;
			    }
    // 			logdebug("FP_Application_Subsystem_Acl.init: Allowing {$rpermission->resource}:{$rpermission->privilege} for role " . $role->getRoleId());
			    $acl->allow($role, $rpermission->resource, $rpermission->privilege);
			}
		    }

		    foreach ($proles as $prole){
			$role_permissions = $prole->getPermissions();

			foreach ($role_permissions as $rpermission){
			    if ($rpermission->resource && $rpermission->privilege){
				if (!in_array($rpermission->resource, $resources)){
				    $acl->addResource(new Zend_Acl_Resource($rpermission->resource));
				    $resources[] = $rpermission->resource;
				}
    // 			    logdebug("FP_Application_Subsystem_Acl.init: Allowing {$rpermission->resource}:{$rpermission->privilege} for role " . $prole->getRoleId());
				$acl->allow($prole, $rpermission->resource, $rpermission->privilege);
			    }
			}
		    }

		}

		unset($parents);
		unset($proles);
	    }

	    $permissions = array();

	    include(BASE_DIR . 'config/permissions.php');

	    foreach ($permissions as $permission){

		foreach ($permission['roles'] as $role){
//  		    logdebug("FP_Application_Subsystem_Acl.init: Allowing Role={$role} Resource={$permission['resource']} Permission={$permission['privilege']}");
		    $acl->allow('role-' . strtolower($role), $permission['resource'], $permission['privilege']);

		}

	    }

	    if (FP_Application::HasIdentity()){

		$user = FP_Application::getIdentity();

		if ($user){

		    $role = $user->getRole();
		    $acl->addRole($user, array($role, 'role-guest'));

		    $permissions = $user->getPermissions();

		    foreach ($permissions as $upermission){

			if ($upermission->resource && $upermission->privilege){
			    if (!in_array($upermission->resource, $resources)){
				$acl->addResource(new Zend_Acl_Resource($upermission->resource));
				$resources[] = $upermission->resource;
			    }
			}
		    }

		    foreach ($permissions as $upermission){
			if ($upermission->resource && $upermission->privilege){
// 			    logdebug("FP_Application_Subsystem_Acl.init: Allowing {$upermission->resource}.{$upermission->privilege} for user {$user->username} (Permission {$upermission->permission_id})");
			    if ($upermission->resource && $upermission->privilege)
				$acl->allow($user, $upermission->resource, $upermission->privilege);
			}
		    }
		} else {
		    logdebug('FP_Application_Subsystem_Acl.init: User session expired');
		    FP_Application::DeAuthenticate();
		}
	    } else
		logdebug('FP_Application_Subsystem_Acl.init: User is a guest');


	    unset($roles);
	    unset($permissions);
	    unset($Roles);

	    Zend_Controller_Front::getInstance()->registerPlugin(new FP_Controller_Plugin_Acl(), 25);

	    Zend_Registry::set('acl', $acl);
	}
    }


    public static function GetAcl(){
	if (self::$enabled){
	    return Zend_Registry::get('acl');
	}
	return null;
    }


}

?>